﻿using System;
using System.Collections.Generic;
using System.Linq;
using GeoAPI.Geometries;
using NetTopologySuite.Geometries;
using NetTopologySuite.Operation.Polygonize;

namespace HYCodeBase.TopologySuite
{
	internal class PolygonFinder
	{
		internal bool FindPolygon(List<LineString> lstInputLines, out List<Polygon> lstFindedValue, out List<Polygon> lstCreatValue, bool ifSplitInput = false)
		{
			lstFindedValue = new List<Polygon>();
			lstCreatValue = new List<Polygon>();
			bool result;
			try
			{
				this.m_corePolygonizer = new Polygonizer();
				List<IGeometry> list = new List<IGeometry>();
				lstInputLines = (ifSplitInput ? TopologySuiteUtility.GetNodedLineString(lstInputLines, false) : lstInputLines);
				foreach (LineString item in lstInputLines)
				{
					list.Add(item);
				}
				this.m_corePolygonizer.Add(list);
				lstFindedValue = (from n in this.m_corePolygonizer.GetPolygons()
				where n != null && n is Polygon
				select n as Polygon).ToList<Polygon>();
				lstCreatValue = this.GetAllUnionPolygon(lstFindedValue);
				lstCreatValue = (from k in lstCreatValue
				orderby -k.Area
				select k).ToList<Polygon>();
				result = true;
			}
			catch (Exception)
			{
				lstFindedValue = new List<Polygon>();
				result = false;
			}
			return result;
		}

		private List<Polygon> GetAllUnionPolygon(List<Polygon> lstInputPolygons)
		{
			List<Polygon> list = new List<Polygon>();
			List<Polygon> list2 = new List<Polygon>();
			list2.AddRange(lstInputPolygons);
			list.AddRange(lstInputPolygons);
			for (int i = 0; i < list2.Count; i++)
			{
				Polygon polygon = null;
				for (int j = i + 1; j < list2.Count; j++)
				{
					polygon = this.UnionTwoPolygon(list2[i], list2[j]);
					if (null != polygon)
					{
						this.RemoveOnePolygon(ref list, list2[i]);
						this.RemoveOnePolygon(ref list, list2[j]);
						list2.RemoveAt(i);
						j--;
						list2.RemoveAt(j);
						i--;
						j--;
						list2.Add(polygon);
						list.Add(polygon);
						break;
					}
				}
                //null != polygon;
			}
			return list;
		}

		private void RemoveOnePolygon(ref List<Polygon> lstInputPolygons, Polygon inputPolygon)
		{
			if (lstInputPolygons.Contains(inputPolygon))
			{
				lstInputPolygons.Remove(inputPolygon);
			}
		}

		private Polygon UnionTwoPolygon(Polygon inputOne, Polygon inputTwo)
		{
			IntersectionMatrix intersectionMatrix = null;
			if (!BaseRelateOperater.TryGetGeometryRelateStatic(inputOne, inputTwo, out intersectionMatrix) || intersectionMatrix.IsDisjoint())
			{
				return null;
			}
			IGeometry geometry = null;
			if (!BaseBooleanOperater.TryGetOperateResultStatic(inputOne, inputTwo, BooleanOperatorKindEnum.Union, out geometry) || geometry == null || !(geometry is Polygon))
			{
				return null;
			}
			return geometry as Polygon;
		}

		private Polygonizer m_corePolygonizer = new Polygonizer();
	}
}
